Date.prototype.toGString = function () {
  return isNaN (this) ? 'NaN' : [this.getFullYear(), 
  	this.getMonth() > 8 ? this.getMonth() + 1 : '0' + (this.getMonth() + 1),
  	this.getDate() > 9 ? this.getDate() : '0' + this.getDate()
  	].join('-')}
Date.prototype.toIdString = function () {
 	return isNaN (this) ? 'NaN' : [this.getFullYear(),
                                this.getMonth() > 8 ? this.getMonth() + 1 : '0' + (this.getMonth() + 1),
                                this.getDate() > 9 ? this.getDate() : '0' + this.getDate()
                                ].join('')}
Date.oneDay = function () {
  return (1000*60*60*24);
  }
Date.prototype.getDayNumber = function () {
  return (this.getTime()/Date.oneDay()).toFixed(0);
  }
  
var prefs = new gadgets.Prefs();
var tabs = new gadgets.TabSet(__MODULE_ID__, "When");
//Legacy var tabs = new _IG_Tabs(__MODULE_ID__, "When"); 
//Legacy var prefs = new _IG_Prefs();       
var gVenue = prefs.getArray("venue");
var gCustomerId = prefs.getString("customerId");
var gPlace = prefs.getString("location");
var gCountry;
var gAdults = 2;
var gChildren=0;
var gArrivalDate = new Date();
var gDepartureDate = new Date();
var gCountriesWithLocationSupport = ['United States', 'United Kingdom', 'Canada'];
//var gRooms = 1;
var gDuration = 5;
var gQueryTable = {};
var gLatestQueryId;
var gPlace = prefs.getString("location");
var gPlaceTable = {};
var gPlaceLoaded = false;
var gRatesTable = {};
var msg = new gadgets.MiniMessage(__MODULE_ID__);
//Legacy var msg = new _IG_MiniMessage(__MODULE_ID__);
var gMessage;
var gAvailabiltyTabIndex;
var gContactTabIndex = null;
var gItineraryTabIndex;
var gDatesTabIndex;
var gWhereTabIndex;
var gNextTabIndex = 0;
var gBasis = prefs.getArray("basis").toString();
var gId = randomNumber();
var gItinerary = new Itinerary();
var gRetries = 0;
YAHOO.namespace("ginngle");    
	function Rate() {
	  
	}
	function Place() {
	  
	}
	function Venue() {
	  this.rate_data_table = {};
	  this.fetchRatesUrlJSON();
	  }
	Venue.prototype.fetchRatesUrlJSON = function () {
		 	var url = "http://www.google.com/base/feeds/snippets/-/Rates?";
			title = "Room rates - " + year + " - " + gBasis;
			bq = "bq=[venue:"+title+"]";
			bq += "[location:"+gLocation+"]";
			gadgets.io.makeRequest(url, buildRatesTable, params);
			//Legacy _IG_FetchFeedAsJSON(url, this.setRatesUrls, 20)
	}
	Venue.prototype.setRatesUrls = function (obj) {
	  var data = obj.text;
	  if ((!data) || (obj.data.count == 0)) {    
	    if (gRetries < 5) {
	      msg.dismissMessage(gMessage);
	      gRetries ++;
	      gId = randomNumber();
	      setTimeout(function() {
	        fetchRatesUrlJSON();
	       }, 200);            
	     }
	     else {
		     gRetries = 0;
		     gMessage = msg.createStaticMessage("Problem loading rates data - Please try again");
	     }
	     return;
	   }
	   else {
	     var jsonData = obj.data.value.items;
	     gRetries = 0;
	     for (var key in jsonData) {
	       item = jsonData[key]
	       rate_id = this.makeRateDataId(item.customer_id, item.basis, item.year)
	       rate.url = item.rates_sheet
	       rate_data = new RateData();
	       this.rate_data_table[rate_id] = rate_data;  
	     }
	   }
	};    
	Venue.prototype.makeRateDataId = function(customer_id, basis, year) {
		key = customer_id+basis+year;
	  return key;
	}
	function RateData() {
	}
	function Itinerary() {
	}
	Itinerary.prototype.update = function() {                              
		this.event_count = 0;
		this.events = new Array();
		for (q in gQueryTable) {
			query = gQueryTable[q];
			this.events[this.event_count]= new Event(query);
			event = this.events[this.event_count];
			for (r in query.rooms) {
	  		event_items = event.event_items;
	  		room = query.rooms[r];
	  		if (room.selected) {
	    		event_items[event.item_count] = new EventItem(room, event.duration);
	    		event_item = event_items[event.item_count];
	    		event.rate += parseFloat(event_item.rate);
	    		event.total += parseFloat(event_item.total);
	    		event.item_count++;
	    	}
	  	}
	  if (event.item_count > 0) this.event_count ++;
	  }
	return this.event_count;
	}
	Itinerary.prototype.buildDom = function(){      
		if (document.getElementById("itinerary_tab") == null) {
	    itinerary_tab = document.createElement('div');
	    itinerary_tab.setAttribute('id', 'itinerary_tab');      
	    gItineraryTabIndex = gNextTabIndex;
	    gNextTabIndex ++;
	    tabs.addTab("Itinerary", {
	      contentContainer: itinerary_tab,
	      tooltip: "Your itinerary so far"
	      })
	  }
	  else if (document.getElementById("itinerary_div") != null) {
	    old_itinerary_div = document.getElementById("itinerary_div");
	    itinerary_tab = document.getElementById("itinerary_tab");
	    itinerary_tab.removeChild(old_itinerary_div);
	  }
	  table = document.createElement('table');
	  for (var key = 0; key < this.events.length; key ++) {
	    event = this.events[key];
	    if (event.event_items.length == 0) return;
	    table.appendChild(event.getTitle());    
	    table.appendChild(event.getHeader());  
	    for (var item_key = 0; item_key < event.event_items.length; item_key ++) {
	      event_item = event.event_items[item_key];
	      table.appendChild(event_item.getRow(event.query_id));
	    }                                              
	  }
	  itinerary_div = document.createElement('div');    
	  itinerary_div.setAttribute('id', 'itinerary_div');
	  itinerary_tab.appendChild(itinerary_div);  
	  itinerary_div.appendChild(table);
	}
	Itinerary.prototype.bookThis = function(param) {
		if (gContactTabIndex == null) {    
	  	tabs.addTab("Contact", {
	    	contentContainer: document.getElementById("contact_id"),
	    	tooltip: "Enter your contact details"
	   	})
	  }	   
		//a=b; // force an error
		gContactTabIndex = gNextTabIndex;
	 	gNextTabIndex ++;
	 	tabs.setSelectedTab(gContactTabIndex);
	 	return false;
	}
	function Event(query) {
		this.query_id = query.query_id;
		this.event_items = new Array();
		this.item_count = 0;
		this.venue = query.venue;
	  this.arrival_date = query.arrival_date;
	  this.duration = query.duration;
	  this.rate = 0.00;
	  this.total = 0.00;
	}
	Event.prototype.getTitle = function (){
		row = document.createElement('tr');
		title_th = document.createElement('th');
		title_th.setAttribute('colspan', '10');
		title_th.innerHTML = this.venue+" for "+this.duration+" nights from "+this.arrival_date.toDateString();
		row.appendChild(title_th);
		return row;
	}
	Event.prototype.getHeader = function (){
	   row = document.createElement('tr');
	   room_type_th = document.createElement('th');
	   adults_th = document.createElement('th');
	   children_th = document.createElement('th');
	   rate_th = document.createElement('th');
	   total_th = document.createElement('th');
	   room_type_th.innerHTML='Room Type';
	   adults_th.innerHTML = "Adults";
	   children_th.innerHTML = "Children";
	   rate_th.innerHTML = "Rate per Night";
	   total_th.innerHTML = "Total";
	   row.appendChild(room_type_th);
	   row.appendChild(adults_th);
	   row.appendChild(children_th);
	   row.appendChild(rate_th);
	   row.appendChild(total_th);              
	   return row;            
	 }
	 function EventItem(room, duration) {
	   this.room_type = room.room_type;
	   this.room_id = room.room_id;
	   this.adults = room.adults_selected;
	   this.children = room.children_selected;
	   this.rate = room.getRate();
	   this.total = room.getTotal(duration);
	 }
	 EventItem.prototype.getRow = function (query_id){
	   row = document.createElement('tr');        
	   room_type_td = document.createElement('td');
	   adults_td = document.createElement('td');
	   children_td = document.createElement('td');
	   rate_td = document.createElement('td');
	   total_td = document.createElement('td');
	   adults_td.innerHTML=this.adults;
	   children_td.innerHTML=this.children;
	   room_type_td.innerHTML=this.room_type;
	   rate_td.innerHTML = this.rate;
	   total_td.innerHTML = this.total;
	   button_td = document.createElement('td');
	   button = document.createElement('button');
	   button.innerHTML = "Remove";
	   onClick = "gQueryTable."+query_id+".rooms."+this.room_id+".removeFromItinerary()";
	   button.setAttribute('onclick',onClick)
	   button_td.appendChild(button);
	   row.appendChild(room_type_td);
	   row.appendChild(adults_td);
	   row.appendChild(children_td);
	   row.appendChild(rate_td);
	   row.appendChild(total_td);
	   row.appendChild(button_td);
	 return row;                            
	 }
	 
	function Query(customer_id, venue, arrival_date, duration, basis, adults, children) {
	  this.query_id = makeQueryId(customer_id, arrival_date, duration, basis);
	  this.availability_id = this.query_id +'_availability';
	  this.arrival_date = new Date();
	  this.arrival_date.setTime(arrival_date.getTime());
	  this.customer_id = customer_id;
	  this.venue = venue;
	  this.basis = basis;
	  this.adults = adults;
	  this.children = children;
	  this.rates = gRatesTable[gRatesId];
		this.duration = duration;
	}
	Query.prototype.setAvailability = function(jsonData) {
	  this.rooms = {};        
	  this.count = 0;          
	  this.selected_count = 0;
		this.unselected_count = 0;  
	  for (var key in jsonData) {
	    item = jsonData[key];
	    var room_name = item.title.replace(/ /g,'_');
	    var room_id = makeRoomId(this.query_id, room_name)
	    var room_type = item.room_type;
	    this.rooms[room_id] = new Room(this, room_id, room_type, this.adults, this.children);
	    this.rooms[room_id].rates = this.rates[room_type];
	    this.count ++;
	    this.unselected_count ++;
	  }
	}  
	Query.prototype.buildRoomsThatFitTable = function() {
	  this.fit=0;
	  for (r in this.rooms) {
	    this_room = this.rooms[r];
	    this_room_type = this_room.room_type;
	    this_rates = this_room.rates;
	    if (this_rates.max_adults >= this.adults
	      && this_rates.max_children >= this.children
	      && this_rates.max_guests >= (this.adults + this.children)) {
	      this_room.fit = true;        
	      this.fit ++;
	    }
	    else this_room.fit = false;
	  }
	  if (this.fit == 0)
		  return false
	  else {
	    return this.fit;
	  }
	}
	Query.prototype.buildRoomsThatFitDom = function() {
		var html = document.createElement('div');
		fit_id = this.query_id+'$fit';
		html.setAttribute('id',fit_id);
		if (this.count == 0) return;
		if (this.fit < this.count) {
			p = document.createElement('p');
	  	p1="These are the rooms that can accommodate your whole party. There are <a onclick = gQueryTable."+this.query_id+".showAllAvailable()>other rooms</a> available";
	   	p.innerHTML = p1;
	   	html.appendChild(p);
	  }
		table = document.createElement('table');
		table.appendChild(this.getTitle());
		table.appendChild(this.getFitHeader());
		html.appendChild(table);
		for (room_id in this.rooms) {
			room = this.rooms[room_id];
			if ((!room.fit) || (room.selected) || (room.overlap)) continue;
			table.appendChild(room.getFitRow());
		}
	return html;        
	}
	Query.prototype.buildAllRoomsDom = function() {
		var table = document.createElement('table');
	  all_id = this.query_id+'$all';
	  table.setAttribute('id', 'all_id');
	  if (this.count == 0) return false;
	  table.appendChild(this.getTitle());
	  table.appendChild(this.getAllHeader());
	  for (room_id in this.rooms) {
	    room = this.rooms[room_id];
	    if ((room.selected) || (room.overlap)) continue;
	  	room_type_details = room.rates;
	    if ((this.adults > room_type_details.max_adults)
	    	|| (this.children > room_type_details.max_children)
	      || ((this.adults + this_query.children) > room_type_details.max_guests)) {
	      room.adults_selected = 1;
	      room.children_selected = 0;
	    }
	    else {
	    	room.adults_selected = this.adults;
	      room.children_selected = this.children || 0;
	    }
	    table.appendChild(room.getAllRow());
	  };
	  return table;
	}
	Query.prototype.getAllHeader =function() {        
	  header = document.createElement('tr');
	  room_type_header = document.createElement('th');
	  room_type_header.innerHTML = 'Room type';
	  header.appendChild(room_type_header);
	  adults_header = document.createElement('th');
	  adults_header.innerHTML = 'Adults';
	  header.appendChild(adults_header);
	  children_header = document.createElement('th');
	  children_header.innerHTML = 'Children';
	  header.appendChild(children_header);
	  rate_header = document.createElement('th');
	  rate_header.innerHTML = 'Rate';
	  header.appendChild(rate_header);
	  action_header = document.createElement('th');
	  action_header.innerHTML = 'Action';
	  header.appendChild(action_header);
	  return header;
	}  
	Query.prototype.showAllAvailable = function() {
	  allTable = this.buildAllRoomsDom();
	  fit_id = this.query_id+'$fit';
		if (document.getElementById(fit_id) != null){          
	  	tab = document.getElementById(this.availability_id);    
	  	fit = document.getElementById(fit_id);  
	  	tab.removeChild(fit);
		}
	  tab.appendChild(allTable);
	}
	Query.prototype.getTitle = function() {
	  event_title_row = document.createElement('tr');
	  event_title = document.createElement('th');
	  event_title.setAttribute('colspan','10');
	  event_title.innerHTML = "Accommodation available at " + this.venue + " for " + this.duration + " nights from " + this.arrival_date.toDateString();
	  event_title_row.appendChild(event_title);
	  return event_title_row;
	}
	Query.prototype.getFitHeader = function() {
	  row = document.createElement('tr');
	  room_type_th = document.createElement('th');
	  rate_th = document.createElement('th');
	  total_th = document.createElement('th');
	  action_th = document.createElement('th');
	  room_type_th.innerHTML='Room Type';
	  rate_th.innerHTML = "Rate per Night";
	  total_th.innerHTML = "Total";
	  action_th.innerHTML = "Action";
	  row.appendChild(room_type_th);
	  row.appendChild(rate_th);
	  row.appendChild(total_th);
	  row.appendChild(action_th);
		return row;
	}
	function Room(query, room_id, room_type, adults, children) {
	  this.room_id = room_id;
	  this.row_id = this.getRowId();
	  this.row_rate_id = this.getRowRateId();
	  this.room_type = room_type;
	  this.adults_selected = adults;
	  this.children_selected = children;
	  this.selected = false;
	  this.overlap = false;
	  this.children_id = "children_select$" + room_id;
	  this.adults_id = "adults_select$" + room_id;
	  this.children_select_td_id = "children_select_td$" + room_id;
	  this.adults_select_td_id = "adults_select_td$" + room_id;
	  this.query = query;
	}  
	Room.prototype.getRate = function() {
	  rates = this.rates;
	  adult_rate = parseFloat(rates['adult_rates'][this.adults_selected]);
	  child_rate = parseFloat(rates['child_rate']);
	  num_children = parseFloat(this.children_selected);
	  rate = parseFloat(adult_rate+(child_rate * num_children)).toFixed(2);
	  return rate;
	}
	Room.prototype.getTotal = function(duration) {        
	  total = parseFloat(this.getRate() * duration).toFixed(2);
	  return total;
	}
	Room.prototype.setRate = function() {
	  adults = document.getElementById(this.adults_id).value;
	  if (document.getElementById(this.children_id)) {
	    this.children = document.getElementById(this.children_id).value;
	  }
	  else {
	    this.children = 0;
	  }
	  document.getElementById(this.row_rate_id).innerHTML = this.getRate();
	};
	Room.prototype.adultsChanged = function() {
	  this.adults_selected = parseInt(document.getElementById(this.adults_id).value);
	  if (document.getElementById(this.children_id) != null) {
	    old_select = document.getElementById(this.children_id);
	    new_select = this.childrenSelect(this.adults_selected);
	    td = document.getElementById(this.children_select_td_id);
	    td.replaceChild(new_select, old_select) ;
	  }
	  this.setRate();
	}
	Room.prototype.childrenChanged = function(){
	  this.children_selected = parseInt(document.getElementById(this.children_id).value);
	  old_select = document.getElementById(this.adults_id);
		new_select = this.adultsSelect(this.children_selected);
	  td = document.getElementById(this.adults_select_td_id);
	  td.replaceChild(new_select, old_select);
	  this.setRate();
	}
	Room.prototype.addToItinerary = function() {
	  this.selected = true;
	  this.query.selected_count ++;
	  this.query.unselected_count --;                        
	  gItinerary.update();
	  gItinerary.buildDom();
		tabs.setSelectedTab(gItineraryTabIndex);
	  buildAvailabilityDom();
	}
	Room.prototype.removeFromItinerary = function() {
	  this.selected = false;
	  this.query.selected_count --;
	  this.query.unselected_count ++;
	  if (gItinerary.update() > 0) {                                  
		  gItinerary.buildDom();
	    tabs.setSelectedTab(gItineraryTabIndex);
	    buildAvailabilityDom();
	  }
	  else {
	    buildAvailabilityDom();
	    tabs.removeTab(gItineraryTabIndex);
	    gNextTabIndex --;
			gItineraryTabIndex = null;
	    tabs.setSelectedTab(gAvailabilityTabIndex);
	  }
	}
Room.prototype.getAllRow = function() {
  room_id = this.room_id;
  row = document.createElement('tr');
  row.setAttribute('id', this.row_id);
  row_room_type = document.createElement('td');
  row_room_type.innerHTML = this.room_type;
  row.appendChild(row_room_type);
  row_adults_select_td = document.createElement('td');
  row_adults_select_td.setAttribute('id',this.adults_select_td_id);
  row_adults_select = this.adultsSelect(this.children_selected);
  row_adults_select_td.appendChild(row_adults_select);  
  row.appendChild(row_adults_select_td);        
  if (this.rates.max_children > 0) {
    row_children_select_td = document.createElement('td');  
    row_children_select_td.setAttribute('id', this.children_select_td_id);        
    row_children_select = this.childrenSelect(this.adults_selected);
    row_children_select_td.appendChild(row_children_select);
    row.appendChild(row_children_select_td);
    }
  else {
    row_blank_td = document.createElement('td');
    row.appendChild(row_blank_td)
  	}
  row_rate = document.createElement('td');
  row_rate_id = this.row_rate_id;
  row_rate.setAttribute('id', row_rate_id);
  row_rate.innerHTML = this.getRate();
  row_button_td = document.createElement('td');
  row_button_td_id = "row_button_td_" + room_id;
  row_button_td.setAttribute('id',row_button_td_id);
  row_button = document.createElement('button',row_button_td_id);
  row_button.innerHTML = "Add to itinerary";
  on_click = "gQueryTable."+this.query.query_id+".rooms."+room_id+".addToItinerary()";
  row_button.setAttribute('onclick',on_click)
  row_button_id = "row_button_" + room_id;
  row_button.setAttribute('id',row_button_id)
    row_button_td.appendChild(row_button);
    row.appendChild(row_rate);
    row.appendChild(row_button_td);
    return row;
}        
 Room.prototype.getFitRow = function(){
   row = document.createElement('tr');
	 row.setAttribute('id', room.row_id);
	 room_type_td = document.createElement('td');
	 rate_td = document.createElement('td');
	 total_td = document.createElement('td');
	 action_td = document.createElement('td');
	 room_type_td.innerHTML = room.room_type;
	 rate_td.innerHTML = room.getRate();
	 total_td.innerHTML = room.getTotal(this.query.duration);
	 on_click = "gQueryTable." + this.query.query_id + ".rooms." + room_id + ".addToItinerary()";
	 book_button = document.createElement('button');
	 book_button.setAttribute('onclick', on_click);
	 book_button.innerHTML = "Add to Itinerary";
   action_td.appendChild(book_button);
   row.appendChild(room_type_td);
   row.appendChild(rate_td);
   row.appendChild(total_td);
   row.appendChild(action_td);
   return row;
 }      
 Room.prototype.adultsSelect = function(children) {
   rates = this.rates;
   var selected;
   if (document.getElementById(this.adults_id) != null) {
     old_selection = document.getElementById(this.adults_id)
     current_adults = parseInt(old_selection.value);
   }
   else {
     current_adults = this.adults_selected;
   }
   if ((rates.max_adults + children) > rates.max_guests) {
     max_adults = (rates.max_guests - children);
   }
   else {
     max_adults = rates.max_adults;
   }
 	 select_tag = document.createElement('select');
	 select_tag.setAttribute('id', this.adults_id);
	 room = this;
	 select_tag.onchange = function(){ adultsSelectOnChange.call(this);};
	 for (var num_adults = 1; num_adults <= max_adults; num_adults ++) {
	   option = document.createElement('option');
	   if (num_adults == current_adults) {option.setAttribute('selected', 'selected')};
	   option.setAttribute('value',num_adults);
	   option.innerHTML = num_adults;
	   select_tag.appendChild(option);
 }
 return select_tag;
};
Room.prototype.childrenSelect = function(adults) {
  rates = this.rates;
  var selected;
  if (document.getElementById(this.children_id) != null) {
    old_selection = document.getElementById(this.children_id);
    current_children = parseInt(old_selection.value);
  }
  else {
  	current_children = this.children_selected;
  }
  if ((rates.max_children + adults) > rates.max_guests) {
    max_children = (rates.max_guests - adults);
  }
  else {
    max_children = rates.max_children;
  }
  select_tag = document.createElement('select');
  select_tag.setAttribute('id', this.children_id);
  room = this;
  select_tag.onchange = function(){ childrenSelectOnChange.call(this);};
  for (var num_children = 0; num_children <= max_children; num_children ++) {
    option = document.createElement('option');
    option.setAttribute('value', num_children);
    if (num_children == current_children) {option.setAttribute('selected', 'selected')};
    option.innerHTML = num_children;
    select_tag.appendChild(option);
  }
  return select_tag;
};
Room.prototype.getRowId = function(){
  row_id = 'row$'+this.room_id;
  return row_id;
}
Room.prototype.getRowRateId = function(){
  row_rate_id = 'row_rate$'+this.room_id;
  return row_rate_id;
}
YAHOO.ginngle.init = function() {
  function handleArrivalSelect(type,args,obj) {
		newDate = handleSelect(type,args,obj,'arrivalDate');
		gArrivalDate.setTime(newDate.getTime());
		gArrivalDate.setHours(0);
		gDepartureDate.setTime(gArrivalDate.getTime()+Date.oneDay());
		document.getElementById("departureDate").value = gDepartureDate.toDateString();
		YAHOO.ginngle.departureCalendar = new YAHOO.widget.Calendar("departureCalendar","departureCalendarContainer", { title:"Departure date:", close:true, mindate: gDepartureDate, pagedate: gDepartureDate});
		YAHOO.ginngle.departureCalendar.render();
		YAHOO.ginngle.departureCalendar.selectEvent.subscribe(handleDepartureSelect, YAHOO.ginngle.departureCalendar, true);
		YAHOO.ginngle.departureCalendar.selectEvent.subscribe(YAHOO.ginngle.departureCalendar.hide, YAHOO.ginngle.departureCalendar, true);
	}
  function handleDepartureSelect(type,args,obj) {
    handleSelect(type,args,obj,'departureDate');
  }
	function handleSelect(type,args,obj, text_element) {
		var dates = args[0];  
		var date = dates[0];
		var year = date[0], month = date[1], day = date[2];          
		var txtDate1 = document.getElementById(text_element);
		newDate= new Date(Date.parse(month + "/" + day + "/" + year));
		txtDate1.value = newDate.toDateString();
		return newDate;
	}
	YAHOO.ginngle.arrivalCalendar = new YAHOO.widget.Calendar("arrivalCalendar","arrivalCalendarContainer", { title:"Arrival date:", close:true, mindate: gArrivalDate });
  YAHOO.ginngle.arrivalCalendar.render();
  document.getElementById("arrivalDate").value = gArrivalDate.toDateString();
  gDepartureDate.setTime(gArrivalDate.getTime()+Date.oneDay());
  document.getElementById("departureDate").value = gDepartureDate.toDateString();
  YAHOO.ginngle.departureCalendar = new YAHOO.widget.Calendar("departureCalendar","departureCalendarContainer", { title:"Departure date:", close:true, mindate: gDepartureDate});
  YAHOO.ginngle.departureCalendar.render();
  // Listener to show the Arrival date Calendar when the input field is clicked
  YAHOO.util.Event.addListener("arrivalDate", "click", YAHOO.ginngle.arrivalCalendar.show, YAHOO.ginngle.arrivalCalendar, true);
  // Listener to update the Arrival date text field when the calendar date is changed
  YAHOO.ginngle.arrivalCalendar.selectEvent.subscribe(handleArrivalSelect, YAHOO.ginngle.arrivalCalendar, true);
  YAHOO.ginngle.arrivalCalendar.selectEvent.subscribe(YAHOO.ginngle.arrivalCalendar.hide, YAHOO.ginngle.arrivalCalendar, true);  
  // Listener to show the Departure date Calendar when the input field is clicked
  YAHOO.util.Event.addListener("departureDate", "click", YAHOO.ginngle.departureCalendar.show, YAHOO.ginngle.departureCalendar, true);
  // Listener to update the Arrival date text field when the calendar date is changed
  YAHOO.ginngle.departureCalendar.selectEvent.subscribe(handleDepartureSelect, YAHOO.ginngle.departureCalendar, true);
  YAHOO.ginngle.departureCalendar.selectEvent.subscribe(YAHOO.ginngle.departureCalendar.hide, YAHOO.ginngle.departureCalendar, true);
	a=b;
}
function init(){
  tabs.addTab("When", {
    contentContainer: document.getElementById("who_when_where_div"),
    tooltip: "Tell us your arrival & departure dates and the number of guests in your party"
  })
  gDatesTabIndex = gNextTabIndex;
  gNextTabIndex++;
  document.getElementById("adults").value = gAdults;
  document.getElementById("children").value = gChildren;
  gPlace = makePlaceId(gPlace);
  if (gVenue == '') {
  	getPlaceJSON();
  }
  else {
    gPlaceTable[gPlace] = new Place();
    gPlaceTable[gPlace][gVenue] = new Venue();
  }
}
function buildWhereTab() {         
  where_div = document.createElement('div');
  where_div.setAttribute('id','where_div');
  where_intro = document.createElement('p');
  where_intro.innerHTML = 'Which country ';
  where_div.appendChild(where_intro);
  where_form = document.createElement('form');
  where_form.setAttribute('id','where_form');
  where_div.appendChild(where_form);
  country_label = document.createElement('label');
  country_label.setAttribute('for','country');
  country = document.createElement('input');
  country.setAttribute('type','text');
  country.setAttribute('id','where_country');
  country.onchange = function(){countryChanged();}        
  vicinity_div = document.createElement('div');
  vicinity_div.setAttribute('id','vicinity_div');
  vicinity_div.setAttribute('style','display:none');  
  vicinity_label = document.createElement('label');
  vicinity_label.setAttribute('for','vicinity');
  vicinity_label.innerHTML = 'Within'
  vicinity = document.createElement('input');
  vicinity.setAttribute('type','text');
  vicinity.setAttribute('id','vicinity');
  vicinity_div.appendChild(vicinity_label);    
  vicinity_div.appendChild(vicinity);    
  place_div = document.createElement('div');
  place_div.setAttribute('id','place_div');
  place_div.setAttribute('style','display:none');
  place_label = document.createElement('label');
  place_label.setAttribute('for','place');
  place_label.innerHTML = 'Location'
  place = document.createElement('input');
  place.setAttribute('type','text');
  place.setAttribute('id','place');
  place_div.appendChild(place_label);  
  place_div.appendChild(place);  
  search_button = document.createElement('button');
  search_button.setAttribute('value','Search for venue');
  search_button.setAttribute('onclick','findVenue()');
  place_div.appendChild(search_button);
  where_form.appendChild(place_div);
  tabs.addTab("Where", {
    contentContainer: where_div,
    tooltip: "Find a venue"
  })
  gWhereTabIndex = gNextTabIndex;
  gNextTabIndex ++;
}
function countryChanged() {
  gCountry = document.getElementById("where_country").value;
  if (gCountry in gCountriesWithLocationSupport) {
    document.getElementById("vicinity_div").setAttribute('style','');
  }
    document.getElementById("place_div").setAttribute('style','');
}
function checkAvailability() {
  //msg.dismissMessage(gMessage);
  gArrivalDate.setTime(Date.parse(document.getElementById('arrivalDate').value));
  gDepartureDate.setTime(Date.parse(document.getElementById('departureDate').value));
  gAdults = parseInt(document.getElementById('adults').value);
  gChildren = parseInt(document.getElementById('children').value);
  gDuration = (gDepartureDate - gArrivalDate) / Date.oneDay();
  gRatesId = makeRatesId(gCustomerId, gVenue, gBasis, gArrivalDate);
  query_id = makeQueryId(gCustomerId, gArrivalDate, gDuration, gBasis);
  gLatestQuery = query_id;
  //document.getElementById("availability_tab").innerHTML = "";
  if(typeof gRatesTable[gRatesId] == "undefined") {
    fetchRatesJSON();
  }
  else if (typeof gQueryTable[query_id] == "undefined") {
    fetchAvailabilityJSON();
  }
  else {
    query = gQueryTable[query_id];        
    query.adults = gAdults;
    query.children = gChildren;    
    buildAvailabilityDom();
    tabs.setSelectedTab(gAvailabilityTabIndex);
  }      
};		
function getPlaceJSON() {    
	// gMessage = msg.createStaticMessage("Loading venues");
  var params = {};
  params[gadgets.io.RequestParameters.CONTENT_TYPE] = gadgets.io.ContentType.JSON;
  var url = "http://pipes.yahoo.com/pipes/pipe.run?_id=4LvJJWVO3RGyxZncEpPZnA&_render=json";
  url +="&location="+gPlace;  
	try {
    gadgets.io.makeRequest(url, buildplace, params);  
  }
  catch (e) {
    alert ('failed to get location data - '+e);
  }
}      
function buildplace(obj) {
  gVenuesLoaded = false;
  // Returned JS object can be processed as an associative array
  var data = obj.text;
  if ((!data) || (obj.data.count == 0)) {
    if (gRetries < 5) {
      msg.dismissMessage(gMessage);
      gRetries++;
			gId = randomNumber();
      setTimeout(function(){
        getPlaceJSON();
      }, 200);
    }
    else {
      gRetries = 0;
      gMessage = msg.createStaticMessage("Problem loading venues - Please try again");
    }
  }
  else {
    var jsonData = obj.data.value.items;
    gRetries = 0;
    place = new Place();
    place.venues = new Array();
    venues = place.venues;
    for (var key in jsonData) {
      item = jsonData[key];
      venue = new Venue();
      venue.customer_id = item.customer_id;
      venue.id = item.id;
      venue.title = item.title;
      venue.description = item.description;
      venue.grade = item.grade;
      venue.link = item.link;
      venues[key] = venue;
    };
    gPlaceTable[gPlace] = place;
    gPlaceLoaded = true;
  }
};
function buildAvailabilityDom() {
	if (document.getElementById("availability_tab") == null) {
  	availability_tab = document.createElement('div');
   	availability_tab.setAttribute('id', 'availability_tab');  
    gAvailabilityTabIndex = gNextTabIndex;
    gNextTabIndex ++;
    tabs.addTab("Availability", {
    contentContainer: availability_tab,
    tooltip: "Shows the rooms available and rates for each room"
    })
  }
	else if (document.getElementById("all_availability_div") != null) {
   old_availability_div = document.getElementById("all_availability_div");
   availability_tab = document.getElementById("availability_tab");
   availability_tab.removeChild(old_availability_div);
	}
  all_availability_div = document.createElement('div');    
 	all_availability_div.setAttribute('id', 'all_availability_div');
 	table = document.createElement('table');
 	for (query in gQueryTable) {
    this_query = gQueryTable[query];
    if (this_query.unselected_count == 0) continue;
    availability_div = document.createElement('div');    
    availability_div.setAttribute('id', this_query.availability_id);
    if (this_query.buildRoomsThatFitTable()) {
      availability_div.appendChild(this_query.buildRoomsThatFitDom());          
    }
    else if (allTable = this_query.buildAllRoomsDom()) {
      availability_div.appendChild(allTable);
    }
    else {
 		p=document.createElement('p');
   	p.innerHTML = 'No room at the inn.';
   	availability_div.appendChild(p);
    }
   	all_availability_div.appendChild(availability_div);    
  }
    availability_tab.appendChild(all_availability_div);
};
function fetchRatesJSON() {      
  gMessage = msg.createStaticMessage("Loading rates");
  var params = {};
  params[gadgets.io.RequestParameters.CONTENT_TYPE] = gadgets.io.ContentType.JSON;
  var url = "http://pipes.yahoo.com/pipes/pipe.run?_id=5fcc3e8f5631b8ff330beea63b9fd841&_render=json";
  url +="&customer_id="+gCustomerId;
  url +="&venue="+makeVenueId(gVenue);
  url +="&arrival_date="+gArrivalDate.toGString();
  url +="&id="+gId;
  gadgets.io.makeRequest(url, buildRatesTable, params);
};      
function buildRatesTable(obj) {
  msg.dismissMessage(gMessage);
  // Returned JS object can be processed as an associative array
  var data = obj.text;
  if ((!data) || (obj.data.count == 0)) {    
    if (gRetries < 5) {
      msg.dismissMessage(gMessage);
      gRetries ++;
      gId = randomNumber();
      setTimeout(function() {
        fetchRatesJSON();
      }, 200);            
    }
    else {
    gRetries = 0;
    gMessage = msg.createStaticMessage("Problem loading rates - Please try again");
    }
    return;
  }
  else {
    var jsonData = obj.data.value.items;
    gRetries = 0;
    rates_table = new Array();
      for (var key in jsonData) {
        item = jsonData[key];
        rates_table[item.title] = new Rate();
        rates_table[item.title]['adult_rates'] = new Array();
        rates_table[item.title]['max_adults'] = parseFloat(item.max_adults);
        rates_table[item.title]['max_children'] = parseFloat(item.max_children);
        rates_table[item.title]['max_guests'] = parseFloat(item.max_guests);
        typeof item.child == "undefined" ? rates_table[item.title]['child_rate'] = 0 : rates_table[item.title]['child_rate'] = parseFloat(item.child).toFixed(2);
        typeof item.single == "undefined" ? rates_table[item.title]['adult_rates'][1] = 0 : rates_table[item.title]['adult_rates'][1] = parseFloat(item.single).toFixed(2);
        typeof item.double == "undefined" ? rates_table[item.title]['adult_rates'][2] = 0 : rates_table[item.title]['adult_rates'][2] = parseFloat(item.double).toFixed(2);
        typeof item.three == "undefined" ? rates_table[item.title]['adult_rates'][3] = 0 : rates_table[item.title]['adult_rates'][3] = parseFloat(item.three).toFixed(2);
        typeof item.four == "undefined" ? rates_table[item.title]['adult_rates'][4] = 0 : rates_table[item.title]['adult_rates'][4] = parseFloat(item.four).toFixed(2);
        typeof item.five == "undefined" ? rates_table[item.title]['adult_rates'][5] = 0 : rates_table[item.title]['adult_rates'][5] = parseFloat(item.five).toFixed(2);
        typeof item.six == "undefined" ? rates_table[item.title]['adult_rates'][6] = 0 : rates_table[item.title]['adult_rates'][6] = parseFloat(item.six).toFixed(2);
        typeof item.seven == "undefined" ? rates_table[item.title]['adult_rates'][7] = 0 : rates_table[item.title]['adult_rates'][7] = parseFloat(item.seven).toFixed(2);
        typeof item.eight == "undefined" ? rates_table[item.title]['adult_rates'][8] = 0 : rates_table[item.title]['adult_rates'][8] = parseFloat(item.eight).toFixed(2);
        typeof item.nine == "undefined" ? rates_table[item.title]['adult_rates'][9] = 0 : rates_table[item.title]['adult_rates'][9] = parseFloat(item.nine).toFixed(2);
        typeof item.ten == "undefined" ? rates_table[item.title]['adult_rates'][10] = 0 : rates_table[item.title]['adult_rates'][10] = parseFloat(item.ten).toFixed(2);
      };
      gRatesTable[gRatesId] = rates_table;
      fetchAvailabilityJSON();
  }
};        
function fetchAvailabilityJSON() {        
  gMessage = msg.createStaticMessage("Checking for available rooms");
  gAdults = parseInt(document.getElementById('adults').value);
  //gRooms = parseInt(document.getElementById('rooms').value);
  gChildren = parseInt(document.getElementById('children').value);
  var url = "http://pipes.yahoo.com/pipes/pipe.run?_id=b2f26e340739374d3a5e7edd6ced677b&_render=json";
  var aDate = gArrivalDate.toGString();
  var dDate = gDepartureDate.toGString();
  url +="&arrival_date="+aDate;
  url +="&departure_date="+dDate;
  url +="&customer_id="+gCustomerId;
	url +="&venue="+makeVenueId(gVenue);
  url +="&basis="+gBasis;
  url +="&id="+gId;
  var params = {};
  params[gadgets.io.RequestParameters.CONTENT_TYPE] = gadgets.io.ContentType.JSON;
  gadgets.io.makeRequest(url, makeQuery, params);
};
function makeQuery(obj) {
  msg.dismissMessage(gMessage);
  var data = obj.text;
  if (!data) {    
    if (gRetries < 5) {
			gRetries ++;
      msg.dismissMessage(gMessage);
      setTimeout(function() {
        fetchAvailabilityJSON();
      }, 200);
    }
    else {
      gRetries = 0;
      gMessage = msg.createStaticMessage("Problem loading availability - Please try again");
    }
    return;
  }      
  gRetries = 0;
  var jsonData = obj.data.value.items;
  query = new Query(gCustomerId, gVenue, gArrivalDate, gDuration, gBasis, gAdults, gChildren);
  gQueryTable[query.query_id] = query;
  query.setAvailability(jsonData);        
  buildAvailabilityDom();
  tabs.setSelectedTab(gAvailabilityTabIndex);
};
function adultsSelectOnChange(){
	getRoomBySelect(this);
  room.adultsChanged();
}
function childrenSelectOnChange(){
  getRoomBySelect(this);
  room.childrenChanged();
}
function randomNumber() {
  var random = Math.random();
  random= random * 10000000;
  random = random.toFixed();
  return random;
};

 function makeQueryId(customer_id, arrival_date, duration, basis) {
   var basis_id = makeBasisId(basis);
   var query_id = 'q'+customer_id+"_"+arrival_date.getDayNumber().toString()+"_"+duration+"_"+basis_id;
   return query_id;
 }
 function makeRatesId(customer_id, venue, basis, arrival_date) {
   rates_key = 'r'+customer_id+'_'+makeBasisId(basis)+'_'+arrival_date.toIdString();
   return rates_key;
 }
 function makeVenueId(venue) {
   venue_id = venue.replace(/ /g, "+");
   return venue_id;
 }
 function makeBasisId(basis) {
   basis_id = basis.replace(/ /g, "+");
   return basis_id;
 }
 function makeRoomId(query_id, room_name) {
   room_id = query_id+'$'+room_name;
   return room_id;
 }    
 function makePlaceId(gPlace) {
   place_id = gPlace.replace(/, /g,'+');
   place_id = gPlace.replace(/ /g,'+');
   place_id = place_id.replace(/,/g,'+');
   return place_id;                                
 }
 function getRoomBySelect(select) {                              
   id_array=select.id.split('$');
   query_id = id_array[1];
   room_name=id_array[2];
   query = gQueryTable[query_id];
   room = query.rooms[makeRoomId(query_id, room_name)];
   return room;
   }
	// Call init function to initialize and display tabs.
	gadgets.util.registerOnLoadHandler(init);
	// Call init function to initialize calendars
	YAHOO.util.Event.onDOMReady(YAHOO.ginngle.init);